/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule FallbackCompositionState
 */

'use strict'

var _assign = require('object-assign')

var PooledClass = require('./PooledClass')

var getTextContentAccessor = require('./getTextContentAccessor')

/**
 * This helper class stores information about text content of a target node,
 * allowing comparison of content before and after a given event.
 *
 * Identify the node where selection currently begins, then observe
 * both its text content and its current position in the DOM. Since the
 * browser may natively replace the target node during composition, we can
 * use its position to find its replacement.
 *
 * @param {DOMEventTarget} root
 */
function FallbackCompositionState(root) {
  this._root = root
  this._startText = this.getText()
  this._fallbackText = null
}

_assign(FallbackCompositionState.prototype, {
  destructor: function () {
    this._root = null
    this._startText = null
    this._fallbackText = null
  },

  /**
   * Get current text of input.
   *
   * @return {string}
   */
  getText: function () {
    if ('value' in this._root) {
      return this._root.value
    }
    return this._root[getTextContentAccessor()]
  },

  /**
   * Determine the differing substring between the initially stored
   * text content and the current content.
   *
   * @return {string}
   */
  getData: function () {
    if (this._fallbackText) {
      return this._fallbackText
    }

    var start
    var startValue = this._startText
    var startLength = startValue.length
    var end
    var endValue = this.getText()
    var endLength = endValue.length

    for (start = 0; start < startLength; start++) {
      if (startValue[start] !== endValue[start]) {
        break
      }
    }

    var minEnd = startLength - start
    for (end = 1; end <= minEnd; end++) {
      if (startValue[startLength - end] !== endValue[endLength - end]) {
        break
      }
    }

    var sliceTail = end > 1 ? 1 - end : undefined
    this._fallbackText = endValue.slice(start, sliceTail)
    return this._fallbackText
  }
})

PooledClass.addPoolingTo(FallbackCompositionState)

module.exports = FallbackCompositionState
